Lisp 実装仕様
まずは動くものを作るために
REPLのガワを作る
『LISP SYSTEM IMPLEMENTATION』
Lispのデータ構造
REPL(Read-Evaluate-Print Loop)
Read-Evaluate-Print-loopのことをREPLと呼ぶ
日本語訳は「入力、評価、出力のループ」あたり
処理のイメージとしては、
1. シェルのような感じで一つの実行できるlispプログラムを実行
2. 結果を返して表示
3. 1-2を繰り返す
といった感じ
replの例
code:lisp
(car '(1 2 3))
1
read
字句解析、構文解析でS式を読み取る箇所
"(" LPAREN
")" RPAREN
"'" QUOTE
"." DOT
eval
数なら数を返す。
シンボルならシンボルに束縛された値を返す。
クオートがついていたなら何も計算せずそのまま返す。
リストなら関数とみてその値を計算する。
defun、setqのような特殊形式ならそれに応じた処理をする。
print
型に応じた応じた出力を返す
loop
read-eval-printを繰り返す
基本概念
式(expression)
インタプリタは式を評価(evaluation)する。
(+ 137 349)、(* 5 99)
+、*はオペレータ
137、349などはオペランド、演算子(operator)
S式の定義
アトムとはS式である
S式を0個以上並べて()で括ったものもS式である
データ型
integers
symbols
list
(cons 'a (cons 'b nil)
cons cells
セル(cell)というものでデータを管理する。
cell
name
tag
数値(Number)
シンボル(Symbol)
リスト(List)
サブルーチン(SUBR)
引数を評価しないもの(FSUBR)
ビルトイン関数(組込関数)
演算子
+, *, =, <, ',
car, cdr, cons, list, quote, caar, cadr
真偽値t, nil
eq, equal, atom, null
defun
lambda
制御
if, and, or, not, cond
ユーザー定義関数
user-defined functions
変数
global variables
lexically-scoped local variables
クロージャ(closure)
マクロ
ガベージコレクタ(gabage collector)
obarray
code:obarray.lisp
;; obarray のデータ構造:単なるハッシュマップ
(defstruct obarray
(table (make-hash-table :test 'equal)))
(defun make-obarray ()
(make-obarray))
(defun intern (name obarray)
(let ((sym (gethash name (obarray-table obarray))))
(if sym
sym
(let ((new-sym (make-symbol name)))
(setf (gethash name (obarray-table obarray)) new-sym)
new-sym))))
(defun find-symbol (name obarray)
(gethash name (obarray-table obarray)))
(defun symbol-name (sym)
;; symbol 構造体に name スロットがある想定
(symbol-name-slot sym))
確認用
Q. Lisp 実装仕様
Q. REPLの実装の仕方
Q. Read
Q. Eval
Q. Print
Q. Loop
Q. S式
Q. cons cell
Q. アトム
Q. リストを実装
参考
cons cell
Cons Cells (GNU Emacs Lisp Reference Manual)
『やさしいLispの作り方: C言語で作るミニミニLisp処理系』
関連
SICP
SECDマシン
メモ
mal/process/guide.md at master · kanaka/mal
Lispのデータ構造
#Lisp